-module (osmos_format).

-export ([ binary/0,
	   term/0,
	   uint64_vector/0 ]).

-export ([ identity/1 ]).

-include ("osmos_format.hrl").

binary () ->
  ToBinary = fun identity/1,
  FromBinary = fun identity/1,
  #osmos_format { to_binary = ToBinary, from_binary = FromBinary }.

term () ->
  ToBinary = fun erlang:term_to_binary/1,
  FromBinary = fun erlang:binary_to_term/1,
  #osmos_format { to_binary = ToBinary, from_binary = FromBinary }.

uint64_vector () ->
  ToBinary = fun uint64_vector_to_binary/1,
  FromBinary = fun uint64_vector_from_binary/1,
  #osmos_format { to_binary = ToBinary, from_binary = FromBinary }.

identity (X) ->
  X.

uint64_vector_to_binary (Tuple) ->
  uint64_vector_to_binary (Tuple, 1, []).
uint64_vector_to_binary (Tuple, I, Acc) when I =< size (Tuple) ->
  C = element (I, Tuple),
  B = << C:64/big-unsigned-integer >>,
  uint64_vector_to_binary (Tuple, I + 1, [ B | Acc ]);
uint64_vector_to_binary (Tuple, I, Acc) when I > size (Tuple) ->
  iolist_to_binary (lists:reverse (Acc)).

uint64_vector_from_binary (B) ->
  uint64_vector_from_binary (B, []).
uint64_vector_from_binary (<< C:64/big-unsigned-integer, B/binary >>, Acc) ->
  uint64_vector_from_binary (B, [ C | Acc ]);
uint64_vector_from_binary (<<>>, Acc) ->
  list_to_tuple (lists:reverse (Acc)).
